/*
Copyright by Henry Ko and Nicola Nicolici
Developed for the Digital Systems Design course (COE3DQ4)
Department of Electrical and Computer Engineering
McMaster University
Ontario, Canada
*/

`timescale 1ns/100ps
`default_nettype none

module tb_TCalc;

logic Clock_50;
logic Resetn;
logic clrResult;

logic [6:0] DP0_Addr [1:0];
logic [31:0] DP0_Read [1:0];
logic [31:0] DP0_Write [1:0];

logic [6:0] DP1_Addr [1:0];
logic [31:0] DP1_Read [1:0];
logic [31:0] DP1_Write [1:0];

logic _DP0_we0;
logic _DP0_we1;
logic _DP1_we0;
logic _DP1_we1;

logic _start;

logic [31:0] _mulResult;
logic [31:0] _mulOp1;
logic [31:0] _mulOp2;
logic _finish;

// Instantiate the unit under test
TCalc uut (
		.CLOCK_50_I(Clock_50),
		.resetn(Resetn),
		.clearResult(clrResult),
		.DP0_Addr0(DP0_Addr [0]),
		.DP0_Addr1(DP0_Addr [1]),
		.DP0_Read0(DP0_Read[0]),
		.DP0_Read1(DP0_Read[1]),
		.DP1_Addr0 (DP1_Addr [0]),
		.DP1_Write0 (DP1_Write [0]),
		.DP1_we0(_DP1_we0),
		.start(_start),
		.mulResult(_mulResult),
		.mulOp1(_mulOp1),
		.mulOp2(_mulOp2),
		.finish(_finish)
);
Mul32 mul32uut (
    .op1(_mulOp1),
    .op2(_mulOp2),
    .result(_mulResult)
);

DP_RAM0 dpRam0uut (
	.address_a(DP0_Addr [0]),
	.address_b(DP0_Addr [1]),
	.clock(Clock_50),
	.data_a(DP0_Write [0]),
	.data_b(DP0_Write [1]),
	.wren_a(_DP0_we0),
	.wren_b(_DP0_we1),
	.q_a(DP0_Read[0]),
	.q_b(DP0_Read[1])
);
DP_RAM1 dpRam1uut (
	.address_a(DP1_Addr [0]),
	.address_b(DP1_Addr [1]),
	.clock(Clock_50),
	.data_a(DP1_Write [0]),
	.data_b(DP1_Write [1]),
	.wren_a(_DP1_we0),
	.wren_b(_DP1_we1),
	.q_a(DP1_Read[0]),
	.q_b(DP1_Read[1])
);
// Generate a 50 MHz clock
always begin
	# 10;
	Clock_50 = ~Clock_50;
end

task master_reset;
begin
	wait (Clock_50 !== 1'bx);
	@ (posedge Clock_50);
	Resetn = 1'b0;
	// Activate reset for 2 clock cycles
	@ (posedge Clock_50);
	@ (posedge Clock_50);	
	Resetn = 1'b1;	
end
endtask

task start_TCalc;
begin
    wait (Clock_50 !== 1'bx);
    @ (posedge Clock_50);
    _start = 1'b1;
    // Activate start for 1 clock cycles
	@ (posedge Clock_50);
    _start = 1'b0;
end
endtask

integer i;
integer temp;
// Initialize signals
initial begin
	Clock_50 = 1'b0;
	Resetn = 1'b1;
	clrResult = 1'b0;
	$write("Applying master reset...\n");
    master_reset;
    // Apply start signal
    $write("Giving start signal...\n");
    start_TCalc;
	
	#100;
	for (i=0; i<128; i=i+1) begin
	temp = dpRam1uut.altsyncram_component.mem_data[i];
	$write("addr %d data %d\n", i, temp);
	end
	
	@ (posedge uut.finish);
	
    $write("Even_Conv is done. Expect 197  79  248.\n");
    @ (posedge Clock_50);
    @ (posedge Clock_50);
	clrResult=1'b1;
	@ (posedge Clock_50);
    @ (posedge Clock_50);
	clrResult=1'b0;
	@ (posedge Clock_50);
    @ (posedge Clock_50);
	$stop;
end

endmodule
